package com.heze.xunhuan.service.impl;

import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.heze.xunhuan.config.AppConfig;
import com.heze.xunhuan.entity.User;
import com.heze.xunhuan.exception.BusinessException;
import com.heze.xunhuan.mapper.UserMapper;
import com.heze.xunhuan.service.UserService;
import com.heze.xunhuan.utils.WechatUtil;
import com.heze.xunhuan.vo.UserVO;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.Map;

/**
 * 用户服务实现类
 *
 * @author heze-xunhuan
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {

    private final WechatUtil wechatUtil;
    private final AppConfig appConfig;

    @Override
    public User getByOpenid(String openid) {
        LambdaQueryWrapper<User> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(User::getOpenid, openid);
        wrapper.eq(User::getStatus, "active");
        return this.getOne(wrapper);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public User createOrUpdateUser(String openid, String unionid, String nickname, String avatar, Integer gender) {
        User user = getByOpenid(openid);

        if (user == null) {
            // 创建新用户
            user = new User();
            user.setOpenid(openid);
            user.setUnionid(unionid);
            user.setNickname(nickname);
            user.setAvatar(avatar);
            user.setGender(gender);
            user.setVipLevel(0);
            user.setDailyPostCount(0);
            user.setStatus("active");
            user.setDeleted(0);
            user.setCreatedAt(LocalDateTime.now());
            this.save(user);
        } else {
            // 更新用户信息
            user.setNickname(nickname);
            user.setAvatar(avatar);
            user.setGender(gender);
            if (unionid != null) {
                user.setUnionid(unionid);
            }
            this.updateById(user);
        }

        return user;
    }

    @Override
    public String bindPhone(Long userId, String code) {
        // TODO: 实现手机号解密逻辑
        // 这里需要调用微信API解密手机号
        throw new BusinessException("手机号绑定功能待实现");
    }

    @Override
    public UserVO getUserInfo(Long userId) {
        User user = this.getById(userId);
        if (user == null) {
            throw new BusinessException(404, "用户不存在");
        }

        UserVO userVO = new UserVO();
        BeanUtils.copyProperties(user, userVO);
        userVO.setAvatar(user.getAvatar());

        // 解析位置信息
        if (user.getLocationInfo() != null) {
            Map<String, Object> locationMap = JSONUtil.toBean(user.getLocationInfo(), Map.class);
            UserVO.LocationInfo locationInfo = new UserVO.LocationInfo();
            locationInfo.setProvince((String) locationMap.get("province"));
            locationInfo.setCity((String) locationMap.get("city"));
            locationInfo.setDistrict((String) locationMap.get("district"));
            locationInfo.setAddress((String) locationMap.get("address"));
            if (locationMap.get("lat") != null) {
                locationInfo.setLat(Double.parseDouble(locationMap.get("lat").toString()));
            }
            if (locationMap.get("lng") != null) {
                locationInfo.setLng(Double.parseDouble(locationMap.get("lng").toString()));
            }
            userVO.setLocationInfo(locationInfo);
        }

        // 脱敏手机号
        if (user.getPhone() != null && user.getPhone().length() == 11) {
            userVO.setPhone(user.getPhone().substring(0, 3) + "****" + user.getPhone().substring(7));
        }

        return userVO;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateUserInfo(Long userId, UserVO userVO) {
        User user = this.getById(userId);
        if (user == null) {
            throw new BusinessException(404, "用户不存在");
        }

        if (userVO.getNickname() != null) {
            user.setNickname(userVO.getNickname());
        }
        if (userVO.getAvatar() != null) {
            user.setAvatar(userVO.getAvatar());
        }
        if (userVO.getGender() != null) {
            user.setGender(userVO.getGender());
        }
        if (userVO.getLocationInfo() != null) {
            user.setLocationInfo(JSONUtil.toJsonStr(userVO.getLocationInfo()));
        }

        this.updateById(user);
    }

    @Override
    public Boolean checkPostLimit(Long userId) {
        User user = this.getById(userId);
        if (user == null) {
            throw new BusinessException(404, "用户不存在");
        }

        // 检查是否是新的一天
        LocalDate today = LocalDate.now();
        if (user.getLastPostDate() == null || !user.getLastPostDate().equals(today)) {
            // 重置发布数量
            user.setDailyPostCount(0);
            user.setLastPostDate(today);
            this.updateById(user);
        }

        // 获取发布限制，vipLevel > 0 表示VIP用户
        Integer limit = (user.getVipLevel() != null && user.getVipLevel() > 0)
            ? appConfig.getBusiness().getVipDailyPostLimit()
            : appConfig.getBusiness().getDailyPostLimit();

        return user.getDailyPostCount() < limit;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void incrementPostCount(Long userId) {
        User user = this.getById(userId);
        if (user == null) {
            throw new BusinessException(404, "用户不存在");
        }
        
        LocalDate today = LocalDate.now();
        if (user.getLastPostDate() == null || !user.getLastPostDate().equals(today)) {
            user.setDailyPostCount(0);
            user.setLastPostDate(today);
        }
        
        user.setDailyPostCount(user.getDailyPostCount() + 1);
        this.updateById(user);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void resetDailyPostCount() {
        // 每日凌晨重置所有用户的发布数量
        // 这里可以通过定时任务调用
        LambdaQueryWrapper<User> wrapper = new LambdaQueryWrapper<>();
        wrapper.ne(User::getDailyPostCount, 0);
        this.list(wrapper).forEach(user -> {
            user.setDailyPostCount(0);
            user.setLastPostDate(LocalDate.now());
            this.updateById(user);
        });
    }
}

